#ifndef _CAPP_H_
#define _CAPP_H_


namespace math { namespace ui 
{

class GLController : public Controller 
{
public :
	GLController (GLView * _glView, Model * model) : Controller(_glView, model){}
public :

	virtual void OnDraw()
	{
		mp_view->paint(); 
		/*
		if (mp_view->is_valid() == false)
		{
			std::cout<<"paint "<<mp_view <<std::endl;
			mp_view->paint(); 
			mp_view->set_valid(true);
		}
		*/
	}
	void OnResize(int w,int h)
	{
		int x = 0, y = 0 ;
		mp_view->resize(w, h); 
		//mp_view->set_region (w, h, x, y); 
	}
	void OnLButtonDown (int mX, int mY)
	{
		//Running = false ;
		mp_view->setMousePos (mX, mY);
		mp_view->setLButtonDown( true );
	}

	void OnLButtonUp (int mX, int mY)
	{
		//Running = false;
		mp_view->setMousePos (mX, mY);
		mp_view->setLButtonDown( false);
	}

	void OnRButtonDown (int mX, int mY)
	{
		//Running = false ;
		mp_view->setMousePos (mX, mY);
		mp_view->setRButtonDown( true);
	}

	void OnRButtonUp (int mX, int mY)
	{

		mp_view->setMousePos (mX, mY);
		mp_view->setRButtonDown( false);
		mp_view->select_face();
	}

	void OnMButtonDown(int mX, int mY)
	{
		mp_view->setMousePos (mX, mY);
		mp_view->setMButtonDown( true);
	}

	void OnMButtonUp(int mX, int mY)
	{
		mp_view->setMousePos (mX, mY);
	}
	void OnMouseMove(int mX, int mY, int relX, int relY, bool Left,bool Right,bool Middle)
	{
		if (Left) // Middle
		{
			//mp_view->rotateCamera(mX, mY);
		}
		else if (Middle)
		{
			//mp_view->translateCamera (mX, mY);
			mp_view->rotateCamera(mX, mY);
		}
		else if (Right)
		{
			mp_view->zoomCamera (mX, mY);
		}
		mp_view->setMousePos(mX, mY); 
	}

protected :

};

class ButtonController : public GLController 
{
public :
	// initialize mp_view with the pointer button
	ButtonController (Button * button, Model * model ): GLController(button, model)
	{

	}
} ;

class StateButtonController : public GLController 
{
public :
	// initialize mp_view with the pointer button
	StateButtonController (StateButton * button, Model * model ): GLController(button, model)
	{
	}
	void OnLButtonUp (int mX, int mY)
	{
		//Running = false;
		mp_view->setMousePos (mX, mY);
		mp_view->setLButtonDown( false);
		((StateButton * )mp_view)->switch_state (); 
		if (((StateButton * )mp_view)->get_state())
		{
			mp_model->get_solid_grush (); 
		}
		else 
		{
			mp_model->get_gaussian_grush ();
		}
	}
} ;

class SliderController : public GLController
{
public:
	SliderController (Slider * slider, Model * model ): GLController(slider, model)
	{

	}	
} ;

class MeshViewController : public GLController 
{
public :
	enum VIEW_MODE {PAINT_MODE, EDIT_MODE} ;
	MeshViewController  (MeshView * view, Model * model ) : GLController (view, model ), mb_mouse_move(false), m_view_mode (PAINT_MODE){}

	void OnRButtonUp (int mX, int mY)
	{
		//Running = false;
		mp_view->setMousePos (mX, mY);
		mp_view->setRButtonDown( false);

		switch (m_view_mode)
		{
		case PAINT_MODE :
			break ;
		case EDIT_MODE :
			mp_view->select_edge (); 
			break ; 
		}
	}

	void OnLButtonUp (int mX, int mY)
	{
		//Running = false;
		mp_view->setMousePos (mX, mY);
		mp_view->setLButtonDown( false);
		switch (m_view_mode)
		{
		case PAINT_MODE :
			mp_view->paint_model(); 
			break; 
		case EDIT_MODE :
			mp_view->select_face() ;
			break; 
		}
	}

	void OnMouseMove(int mX, int mY, int relX, int relY, bool Left,bool Right,bool Middle)
	{
		mb_mouse_move = true; 
		if (Left) // Middle
		{
			//mp_view->rotateCamera(mX, mY);
		}
		else if (Middle)
		{
			//mp_view->translateCamera (mX, mY);
			mp_view->rotateCamera(mX, mY);
		}
		else if (Right)
		{
			mp_view->zoomCamera (mX, mY);
		}
		mp_view->setMousePos(mX, mY); 

		//mp_view->bfs_culling(); 
	}

	void OnKeyUp (SDLKey sym, SDLMod mod, Uint16 unicode)
	{
		typedef typename Model::mesh_type mesh_type ;
		mesh_type * mesh = this->mp_model->get_mesh(); 

		switch (sym )
		{
		case '\t' : // switch mode 
			if (m_view_mode == PAINT_MODE) m_view_mode = EDIT_MODE;
			else m_view_mode = PAINT_MODE ;
			break ;
		}

		if (sym == 'u' || sym == 'U')
		{
			((MeshView *)(this->mp_view))->up_sampling();
			return ;
		}

		if (sym == 'd' || sym == 'D')
		{
			((MeshView *)(this->mp_view))->down_sampling(); 
			return ;
		}

		if (sym == 'm' || sym == 'M')
		{

			for (unsigned i = 0; i < mesh->faces.size(); ++i)
			{
				bool flag = mesh->faces[i]->get_merge_all_layers();
				mesh->faces[i]->set_merge_all_layers(!flag);
				//MeshView * view = (MeshView *) mp_model->query_control(MESH_VIEW_CTRL);
				((MeshView *)(this->mp_view))->set_update_whole_model();
			}
			return ;
		}
		unsigned id = unsigned (sym - '0'); // Layer zero is not paintable. 
		if (id >= 3) return ; 
		mp_model->set_layer(id);
		for (unsigned i = 0; i < mesh->faces.size(); ++i)
		{
			mesh->faces[i]->set_layer_id(id );
		}
		std::cout<<id<<std::endl;

		((MeshView *)(this->mp_view))->set_update_whole_model(); 
	}
protected:
	bool mb_mouse_move; 
	VIEW_MODE m_view_mode ;
};

}
}


#endif
